# -*- coding: utf-8 -*-
#communication interface between pc application and gateway mote
#@author: Paweł Pawłowski <abdul-pablo@tlen.pl>

from tinyos.message import MoteIF

#import message classes
from DataRequestMsgToGateway import DataRequestMsgToGateway
from SystemStateMsgToUSB import SystemStateMsgToUSB
from SystemAlertMsgToUSB import SystemAlertMsgToUSB
from ValveControlMsgToGateway import ValveControlMsgToGateway

#source must be set according to rules specified by TinyOS SDK developers
#SOURCE = 'serial@/dev/ttyUSB0:micaz'
SOURCE = 'sf@metro:9002'


class WSNSerialComm:
    """Serial communication interface class"""
    WATER_MSG_FLAG =  1
    HUMIDITY_MSG_FALG = 2
    VALVE_MSG_FLAG = 4

    DataRequestMsgTypeID = 0x10
    ValveControlMsgTypeID = 0x12

    ALERTS = { 1 : 'No alert', 2 : 'Alarm: Water is below minimum level',
               3 : 'Warning: Water is below warning level', 4 : 'Emergency alarm: Soil is dry and water is below minimum level' }

    def __init__(self, humidityCallback, waterCallback, valveCallback, displayMsgCallback, alertCallback, group = 0):
        # Create a MoteIF
        self.mif = MoteIF.MoteIF()
        # Attach a source to it
        self.source = self.mif.addSource(SOURCE)

        # SomeMessageClass.py would be generated by MIG
        self.mif.addListener(self, SystemStateMsgToUSB)
        self.mif.addListener(self, SystemAlertMsgToUSB)

        #save callback functions
        self.humidityCallback = humidityCallback
        self.waterCallback = waterCallback
        self.valveCallback = valveCallback
        self.displayMsgCallback = displayMsgCallback
        self.alertCallback = alertCallback

    def receive(self, src, msg):
        """Called by the MoteIF's receive thread when a new message is received"""

        print 'Message received'
        self.displayMsgCallback.__call__("Received message: "+ str(msg)+"\n") #print message in text field
        if hasattr(msg, 'get_water'):
            self.waterCallback(int(msg.get_water()))
        if hasattr(msg, 'get_valve'):
            self.valveCallback(int(msg.get_valve()))
        if hasattr(msg, 'get_humidity'):
            self.humidityCallback(int(msg.get_humidity()))
        if hasattr(msg, 'get_alert'):
            self.alertCallback(self.ALERTS[int(msg.get_alert())])

    def sendValveControlMsg(self, valve, group = 0, dest = 0xffff):
        """Sends valve control message to gateway"""

        msg = ValveControlMsgToGateway()
        msg.set_valve(int(valve))

        addr = dest
        amType = msg.get_amType()
        self.mif.sendMsg(self.source, addr, amType, group, msg)
        self.displayMsgCallback.__call__("Sent message: "+ str(msg)+"\n")

    def sendDataRequestMsg(self, requested_data_tuple = (), renew_tuple = (), group = 0, dest = 0xffff):
        """Sends data request message to gateway"""

        msg = DataRequestMsgToGateway()

        requested_data_int = 0
        if 'valve' in requested_data_tuple:
            requested_data_int = requested_data_int + self.VALVE_MSG_FLAG
        if 'water' in requested_data_tuple:
            requested_data_int = requested_data_int + self.WATER_MSG_FLAG
        if 'humidity' in requested_data_tuple:
            requested_data_int = requested_data_int  + self.HUMIDITY_MSG_FALG

        renew_int = 0
        if 'water' in renew_tuple:
            renew_int = renew_int + self.WATER_MSG_FLAG
        if 'humidity' in renew_tuple:
            renew_int = renew_int  + self.HUMIDITY_MSG_FALG

        msg.set_requested_data(requested_data_int)
        msg.set_renew(renew_int)

        amType = msg.get_amType()
        addr = dest
        self.mif.sendMsg(self.source, addr, amType, group, msg)
        self.displayMsgCallback.__call__("Sent message: "+ str(msg)+"\n")
